package cn.singno.bob.coffice.utils;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

import cn.singno.bob.coffice.bean.WordDocument;
import cn.singno.bob.coffice.bean.Word4Image;
import cn.singno.bob.common.exception.FileOperateException;
import cn.singno.bob.common.utils.EntityUtils;

/**
 * <p>名称：WordUtils.java</p>
 * <p>描述：word工具类</p>
 * <pre>
 *    操作word文档的工具类，
 * 	     该类暂时提供按模板的形式导出word
 * 说明：模板格式请参照项目中word模板的格式 
 * 图片的key 为:photo
 * </pre>
 * @author 鲍建明
 * @date 2014年8月6日 下午12:37:11
 * @version 1.0.0
 */
public class WordUtils {
	
	private static Log logger = LogFactory.getLog(WordUtils.class);

	/**
	 * 根据指定的参数值、模板，生成 word 文档
	 * @param param 需要替换的变量
	 * @param templateFile 模板
	 * @throws FileOperateException 
	 */
	public static WordDocument generateWord(Map<String, Object> param, String templateFile) throws FileOperateException {
		WordDocument doc = null;
		try {
			OPCPackage pack = POIXMLDocument.openPackage(templateFile);
			doc =  new WordDocument(pack);
			if (param != null && param.size() > 0) {
				
				//处理段落
				List<XWPFParagraph> paragraphList = doc.getParagraphs();
				processParagraphs(paragraphList, param, doc);
				
				//处理表格
				Iterator<XWPFTable> it = doc.getTablesIterator();
				while (it.hasNext()) {
					XWPFTable table = it.next();
					List<XWPFTableRow> rows = table.getRows();
					for (XWPFTableRow row : rows) {
						List<XWPFTableCell> cells = row.getTableCells();
						for (XWPFTableCell cell : cells) {
							List<XWPFParagraph> paragraphListTable =  cell.getParagraphs();
							processParagraphs(paragraphListTable, param, doc);
						}
					}
				}
			}
		} catch (IOException e) {
			logger.error(e);
			throw new FileOperateException("读取word模板失败");
		} 
		return doc;
	}
	
	public static WordDocument generateWord(Object obj, String templateFile) throws FileOperateException{
		Map<String, Object> param = EntityUtils.describe(obj);
		return generateWord(param, templateFile);
	}
	
	public static WordDocument generateWord(Object obj, Word4Image img,  String templateFile) throws FileOperateException{
		Map<String, Object> param = EntityUtils.describe(obj);
		Map<String, Object> map = EntityUtils.describe(img);
		param.put("photo", map);
		return generateWord(param, templateFile);
	}
	
	public static  WordDocument generateWord(Map<String, Object> param, Word4Image img, String templateFile) throws FileOperateException{
		Map<String, Object> map = EntityUtils.describe(img);
		map.put("image", img.getFile());
		param.put("photo", map);
		return generateWord(param, templateFile);
	}
	
	
	/**
	 * 处理段落
	 * @param paragraphList
	 * @throws FileOperateException 
	 */
	public static void processParagraphs(List<XWPFParagraph> paragraphList,Map<String, Object> param,WordDocument doc) throws FileOperateException{
		if (paragraphList != null && paragraphList.size() > 0) {
			for (XWPFParagraph paragraph : paragraphList) {
				List<XWPFRun> runs = paragraph.getRuns();
				for (int i = 0; i < runs.size(); i++) {
					XWPFRun run = runs.get(i);
					String text = run.getText(0);
					if (StringUtils.isNotBlank(text)) {
						boolean isSetText = false;
						for (Entry<String, Object> entry : param.entrySet()) {
							String key = entry.getKey();
							if (text.indexOf(key) != -1) {
								isSetText = true;
								Object value = entry.getValue();
								if (value instanceof String) {// 文本替换
									text = text.replace("{{" + key + "}}",
											value.toString());
								} else if (value instanceof Map) {// 图片替换
									text = text.replace("{{" + key + "}}", "");
									Map pic = (Map) value;
									int width = Integer.parseInt(pic.get(
											"width").toString());
									int height = Integer.parseInt(pic.get(
											"height").toString());
									int picType = getPictureType(pic
											.get("type").toString());
									Object phoneTitle = pic.get("photoTitle");
									byte[] byteArray = (byte[]) pic
											.get("image");
									ByteArrayInputStream byteInputStream = new ByteArrayInputStream(
											byteArray);
									try {

										doc.addPictureData(byteInputStream,
												picType); // "rId8
										doc.createPicture(
												doc.getAllPictures().size() - 1,
												width,
												height,
												paragraph,
												phoneTitle == null ? "" : phoneTitle.toString());
									} catch (Exception e) {
										logger.error(e);
										throw new FileOperateException("创建word图片失败");
									}
								}
							}
						}
						if (isSetText) {
							run.setText(text, 0);
						}
					}
				}
			}
		}
	}
	/**
	 * 根据图片类型，取得对应的图片类型代码
	 * @param picType
	 * @return int
	 * @throws FileOperateException 
	 */
	private static int getPictureType(String picType) throws FileOperateException{
		//java 7
		int res = WordDocument.PICTURE_TYPE_PICT;
		switch (picType) {
		case "png":
			res = WordDocument.PICTURE_TYPE_PNG;
			break;
		case "dib":
			res = WordDocument.PICTURE_TYPE_DIB;
			break;
		case "emf":
			res = WordDocument.PICTURE_TYPE_EMF;
			break;
		case "jpg":
			res = WordDocument.PICTURE_TYPE_JPEG;
			break;
		case "jpeg":
			res = WordDocument.PICTURE_TYPE_JPEG;
			break;
		case "wmf":
			res = WordDocument.PICTURE_TYPE_WMF;
			break;
		default:
			throw new FileOperateException("未知图片类型");
		}
		return res;
		
		/* java 6
		 * int res = CustomXWPFDocument.PICTURE_TYPE_PICT;
		if(picType != null){
			if(picType.equalsIgnoreCase("png")){
				res = CustomXWPFDocument.PICTURE_TYPE_PNG;
			}else if(picType.equalsIgnoreCase("dib")){
				res = CustomXWPFDocument.PICTURE_TYPE_DIB;
			}else if(picType.equalsIgnoreCase("emf")){
				res = CustomXWPFDocument.PICTURE_TYPE_EMF;
			}else if(picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")){
				res = CustomXWPFDocument.PICTURE_TYPE_JPEG;
			}else if(picType.equalsIgnoreCase("wmf")){
				res = CustomXWPFDocument.PICTURE_TYPE_WMF;
			}
		}
		return res;*/
	}
	
	
	
	
	
	
}